<template>
  <view class="uv-drop-down-popup">
    <uv-transition :show="show" mode="fade" :duration="300" :custom-style="overlayStyle" @click="clickOverlay">
      <view class="uv-dp__container" ref="uvDPContainer" :style="{ height: `${height}px` }" @click.stop="blockClick">
        <view class="uv-dp__container__list" ref="uvDPList">
          <slot>
            <view
              class="uv-dp__container__list--item"
              v-for="(item, index) in list"
              :key="index"
              @click="clickHandler(item, index)"
              :style="[itemCustomStyle(index)]"
            >
              <uv-text :text="item[keyName]" :size="getTextSize(index)" :color="getTextColor(index)"></uv-text>
            </view>
          </slot>
        </view>
      </view>
    </uv-transition>
  </view>
</template>
<script>
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
// #ifdef APP-NVUE
const animation = uni.requireNativePlugin('animation')
const dom = uni.requireNativePlugin('dom')
// #endif
/**
 * DropDownPopup 下拉框
 * @description 下拉筛选框
 * @tutorial https://ext.dcloud.net.cn/plugin?name=uv-drop-down
 * @property {String | Number} name 字段标识
 * @property {String | Number} zIndex 弹出层的层级
 * @property {String | Number} opacity 遮罩层的透明度
 * @property {Boolean} clickOverlayOnClose 是否允许点击遮罩层关闭弹窗
 * @property {Object} currentDropItem 当前下拉筛选菜单对象
 * @property {String} keyName 指定从当前下拉筛选菜单对象元素中读取哪个属性作为文本展示
 */
export default {
  name: 'uv-drop-down-popup',
  mixins: [mpMixin, mixin],
  props: {
    sign: {
      type: [String, Number],
      default: 'UVDROPDOWN',
    },
    zIndex: {
      type: [Number, String],
      default: 999,
    },
    opacity: {
      type: [Number, String],
      default: 0.5,
    },
    clickOverlayOnClose: {
      type: Boolean,
      default: true,
    },
    // 当前下拉选项对象
    currentDropItem: {
      type: Object,
      default() {
        return {
          activeIndex: 0,
          child: [],
        }
      },
    },
    keyName: {
      type: String,
      default: 'label',
    },
  },
  data() {
    return {
      show: false,
      rect: {},
      height: 0,
    }
  },
  computed: {
    overlayStyle() {
      let { height = 0, top = 0 } = this.rect
      // #ifdef H5
      top += this.$uv.sys().windowTop
      // #endif
      const style = {
        position: 'fixed',
        top: `${top + height}px`,
        left: 0,
        right: 0,
        zIndex: this.zIndex,
        bottom: 0,
        'background-color': `rgba(0, 0, 0, ${this.opacity})`,
      }
      return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle))
    },
    list() {
      try {
        return Array.isArray(this.currentDropItem.child) ? this.currentDropItem.child : []
      } catch (e) {
        return []
      }
    },
    getTextColor(index) {
      return (index) => {
        const active = this.currentDropItem.activeIndex == index
        const color = this.currentDropItem.color
        const activeColor = this.currentDropItem.activeColor
        if (active) {
          return activeColor ? activeColor : '#3c9cff'
        }
        return color ? color : '#333'
      }
    },
    getTextSize(index) {
      return (index) => {
        const active = this.currentDropItem.activeIndex == index
        const size = this.currentDropItem.size
        const activeSize = this.currentDropItem.activeSize
        if (active) {
          return activeSize ? activeSize : '30rpx'
        }
        return size ? size : '30rpx'
      }
    },
    itemCustomStyle() {
      return (index) => {
        const active = this.currentDropItem.activeIndex == index
        const style = {}
        if (active && this.currentDropItem.itemActiveCustomStyle) {
          return this.$uv.deepMerge(style, this.$uv.addStyle(this.currentDropItem.itemActiveCustomStyle))
        }
        if (this.currentDropItem.itemCustomStyle) {
          return this.$uv.deepMerge(style, this.$uv.addStyle(this.currentDropItem.itemCustomStyle))
        }
        return style
      }
    },
  },
  created() {
    this.init()
  },
  methods: {
    blockClick() {},
    clickHandler(item, index) {
      this.currentDropItem.activeIndex = index
      this.$emit('clickItem', item)
      this.close()
    },
    init() {
      uni.$off(`${this.sign}_GETRECT`)
      uni.$on(`${this.sign}_GETRECT`, (rect) => {
        this.rect = rect
      })
      uni.$off(`${this.sign}_CLICKMENU`)
      uni.$on(`${this.sign}_CLICKMENU`, async (res) => {
        if (res.show) {
          this.open()
        } else {
          this.close()
        }
      })
    },
    open() {
      this.show = true
      this.$nextTick(async () => {
        // #ifndef H5 || MP-WEIXIN
        await this.$uv.sleep(60)
        // #endif
        const res = await this.queryRect()
        // #ifndef APP-NVUE
        this.height = res.height
        // #endif
        // #ifdef APP-NVUE
        this.animation(res.height)
        // #endif
        this.$emit('popupChange', { show: true })
      })
    },
    close() {
      if (!this.show) return
      this.height = 0
      // #ifndef APP-NVUE
      this.height = 0
      // #endif
      // #ifdef APP-NVUE
      this.animation(0)
      // #endif
      this.show = false
      uni.$emit(`${this.sign}_CLOSEPOPUP`)
      this.$emit('popupChange', { show: false })
    },
    clickOverlay() {
      if (this.clickOverlayOnClose) {
        this.close()
      }
    },
    // 查询内容高度
    queryRect() {
      // #ifndef APP-NVUE
      // 组件内部一般用this.$uvGetRect，对外的为getRect，二者功能一致，名称不同
      return new Promise((resolve) => {
        this.$uvGetRect(`.uv-dp__container__list`).then((size) => {
          resolve(size)
        })
      })
      // #endif
      // #ifdef APP-NVUE
      // nvue下，使用dom模块查询元素高度
      // 返回一个promise，让调用此方法的主体能使用then回调
      return new Promise((resolve) => {
        dom.getComponentRect(this.$refs.uvDPList, (res) => {
          resolve(res.size)
        })
      })
      // #endif
    },
    // nvue下设置高度
    animation(height, duration = 200) {
      // #ifdef APP-NVUE
      const ref = this.$refs['uvDPContainer']
      animation.transition(ref, {
        styles: {
          height: `${height}px`,
        },
        duration,
      })
      // #endif
    },
  },
}
</script>
<style scoped lang="scss">
.uv-dp__container {
  /* #ifndef APP-NVUE */
  overflow: hidden;
  transition: all 0.15s;
  /* #endif */
  background-color: #fff;
}
.uv-dp__container__list {
  &--item {
    padding: 20rpx 60rpx;
  }
}
</style>
